package com.partsoft.dits;

import java.lang.reflect.Array;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.springframework.util.Assert;

import com.partsoft.dits.AbstractDescriptorRegistry;

/**
 * 抽象的描述符管理器实现
 * @param <E>
 */
@SuppressWarnings("unchecked")
public abstract class AbstractDescritptorManager<E extends EdgeDescriptor> extends AbstractDescriptorRegistry<E> implements DescriptorManager<E> {
	
	private Map<String, E> descriptorIdsMap = Collections.synchronizedMap(new HashMap<String, E>(5));
	
	/**
	 * 获得描述符映射表（默认为同步实现HASHMAP）
	 */
	protected Map<String, E> getDescriptorMap() {
		return descriptorIdsMap;
	}
	
	protected void setDescriptorIdsMap(Map<String, E> descriptorIdsMap) {
		this.descriptorIdsMap = descriptorIdsMap;
	}

	/**
	 * TODO 需要考虑速度优化问题。
	 */
	public E[] getDescriptors() {
		List<E> returnList = new LinkedList<E>();
		for (E descriptor : descriptorIdsMap.values()) {
			returnList.add((E) descriptor.clone());
		}
		Collections.sort(returnList, new Comparator<E>() {
			public int compare(E o1, E o2) {
				return o1.getOrdinal() - o2.getOrdinal();
			}
		});
		E[] returnArray = (E[]) Array.newInstance(getSupportClass(), 0); 
		return returnList.toArray(returnArray);
	}
	
	public E[] getDescriptors(DescriptorAccepter<E> accepter) {
		if (accepter == null) return this.getDescriptors();
		List<E> returnList = new LinkedList<E>();
		for (E descriptor : descriptorIdsMap.values()) {
			if (accepter.accept(descriptor)) returnList.add((E) descriptor.clone());
		}
		Collections.sort(returnList, new Comparator<E>() {
			public int compare(E o1, E o2) {
				return o1.getOrdinal() - o2.getOrdinal();
			}
		});
		E[] returnArray = (E[]) Array.newInstance(getSupportClass(), 0); 
		return returnList.toArray(returnArray);
	}
	
	public E addDescriptor(E descriptor) {
		Assert.notNull(descriptor);
		synchronized (this) {
			String id = resolveDescriptorIdentifier(descriptor);
			Assert.isTrue(!hasDescriptor(id));
			descriptorIdsMap.put(id, descriptor);
			return descriptor;
		}
	}
	
	public E removeDescriptor(E descriptor) {
		Assert.notNull(descriptor);
		return removeDescriptor(resolveDescriptorIdentifier(descriptor));
	}

	public E modifyDescriptor(E descriptor) {
		Assert.notNull(descriptor);
		synchronized (this) {
			removeDescriptor(descriptor);
			return addDescriptor(descriptor);
		}
	}
	
	public E getDescriptor(E descriptor) {
		return getDescriptor(resolveDescriptorIdentifier(descriptor));
	};
	
	public boolean hasDescriptor(E descriptor) {
		Assert.notNull(descriptor);
		return descriptorIdsMap.containsKey(resolveDescriptorIdentifier(descriptor));
	}
	
	public E getDescriptor(String id) {
		Assert.isTrue(hasDescriptor(id), String.format("找不到id=%s的描述符", id));
		return (E) descriptorIdsMap.get(id).clone();
	}

	public boolean hasDescriptor(String id) {
		return descriptorIdsMap.containsKey(id);
	}

	public E removeDescriptor(String id) {
		synchronized (this) {
			return descriptorIdsMap.remove(id);
		}
	}
	
	public int countDescriptor() {
		return descriptorIdsMap.size();
	}
	
	public int countDescriptor(DescriptorAccepter<E> accepter) {
		if (accepter == null) return this.countDescriptor();
		int result = 0;
		for (E descriptor : descriptorIdsMap.values()) {
			if (accepter.accept(descriptor)) result++;
		}
		return result;
	}

	/**
	 * 获得描述符的标识符
	 * @param descriptor 描述符对象
	 * @return 标识符
	 */
	protected abstract String resolveDescriptorIdentifier(E descriptor);
	
}
